library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;


entity Register_File is
generic (	N 		: positive := 4;		--number of bits in the registers
		N_ADDR	: positive := 2);		--address size (determines number of registers)
port( clock 	  : in  std_logic;
		reset 	  : in  std_logic;
		port_S_addr: in  std_logic;
		port_T_addr: in  std_logic;
		port_D_addr: in  std_logic_vector (N_ADDR-1 downto 0);
		write_D_EN : in  std_logic;
		port_D_IN  : in  std_logic_vector (N-1 downto 0);  --content to be written (Data In)
		port_S_OUT : out std_logic_vector (N-1 downto 0);  --content to be read
		port_T_OUT : out std_logic_vector (N-1 downto 0)   --content to be read
);
end Register_File;

architecture Behavioral of Register_File is
constant N_REGS : positive := 2**N_ADDR;

subtype register_address is natural range 0 to N_REGS-1;
type register_array is array (register_address) of std_logic_vector(N-1 downto 0);

signal reg : register_array;
signal en  : std_logic_vector (N_REGS-1 downto 0);
signal S_index : natural range 0 to 1;
signal T_index : natural range 0 to 1;
begin

	--registers generation
	generic_ff: for i in 0 to N_REGS-1 generate
		reg_i: entity ffdcN generic map(N)
		port map (clock,reset,en(i),port_D_IN,reg(i));
	end generate;

	process (clock)
	begin
		if rising_edge(clock)
		then
			for i in 0 to N_REGS-1 loop
				if write_D_EN = '1' and i = to_integer(unsigned(port_D_addr))
				then
					en(i) <= '1';
				else
					en(i) <= '0';
				end if;
			end loop;
		end if;
	end process;

S_index <= 0 when port_S_addr = '0' else 1;
T_index <= 0 when port_T_addr = '0' else 1;

	port_S_OUT <= reg(S_index);    --first register
	port_T_OUT <= reg(T_index);    --second register

end Behavioral;
